package com.kky.pp.pay

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.util.Log
import com.android.billingclient.api.AcknowledgePurchaseParams
import com.android.billingclient.api.BillingClient
import com.android.billingclient.api.BillingClient.BillingResponseCode
import com.android.billingclient.api.BillingClientStateListener
import com.android.billingclient.api.BillingFlowParams
import com.android.billingclient.api.BillingResult
import com.android.billingclient.api.ConsumeParams
import com.android.billingclient.api.ConsumeResponseListener
import com.android.billingclient.api.ProductDetails
import com.android.billingclient.api.Purchase
import com.android.billingclient.api.Purchase.PurchaseState
import com.android.billingclient.api.PurchasesUpdatedListener
import com.android.billingclient.api.QueryProductDetailsParams
import com.android.billingclient.api.QueryPurchasesParams
import com.custom.base.entity.OkHttpBodyEntity
import com.custom.base.http.OkHttpFromBoy
import com.custom.base.http.OkHttpManager
import com.custom.base.http.SDOkHttpResoutCallBack
import com.custom.base.manager.SDActivityManager
import com.custom.base.util.ToastUtil
import com.kky.pp.popup.MemberBuySuccessPopup
import com.custom.base.base.SDEventManager
import com.kky.pp.callback.EmptySuccessCallBack
import io.rong.common.CollectionUtils
import io.rong.dot.DotInit
import io.rong.imkit.API
import io.rong.imkit.dialog.MemberBuySingleSuccessDialog
import io.rong.imkit.entity.OrderCreateEntity
import io.rong.imkit.event.EnumEventTag


class GooglePayUtils {

    private var activity: Activity=SDActivityManager.instance.lastActivity
    private var context:Context?=null
    private var mBillingResult: BillingResult?=null
    private var startConnectionNumber=0
    private var data: OrderCreateEntity?=null

    private val purchasesUpdatedListener = PurchasesUpdatedListener { billingResult, purchases ->
        //购买结果监听
        when (billingResult.responseCode) {
            BillingResponseCode.OK -> {
                onPurchasesUpdated(billingResult, purchases)
            }
            BillingResponseCode.DEVELOPER_ERROR->{

            }
            BillingResponseCode.ITEM_ALREADY_OWNED ->{
                data?.apply {
                    val queryPurchasesParams = QueryPurchasesParams.newBuilder()
                        .setProductType(if (this.data.purchaseType == 1) BillingClient.ProductType.INAPP else BillingClient.ProductType.SUBS)
                        .build()

                    billingClient.queryPurchasesAsync(queryPurchasesParams
                    ) { _, p1 ->
                        for(pur in p1){
                            if (!pur.isAcknowledged && pur.purchaseState == PurchaseState.PURCHASED) {
                                storeToken(pur)
                            }
                        }

                    }
                }

            }
            else -> {
                handleBillingResult(314,billingResult)
            }
        }
    }

    private var billingClient: BillingClient = BillingClient.newBuilder(activity)
        .setListener(purchasesUpdatedListener)
        .enablePendingPurchases()
        .build()
    private var callBack: EmptySuccessCallBack? = null
    private var mEntity: OrderCreateEntity? = null
    private val billingClientStateListener =object : BillingClientStateListener {

        override fun onBillingSetupFinished(billingResult: BillingResult) {
            mBillingResult=billingResult
            DotInit.listenet?.oldExecute(311,"connected success")
        }

        override fun onBillingServiceDisconnected() {
            // Try to restart the connection on the next request to
            // Google Play by calling the startConnection() method.
            if (startConnectionNumber<3){
                billingClient.startConnection(this)
                startConnectionNumber++
            }
        }
    }

    companion object {
        @SuppressLint("StaticFieldLeak")
        private var mInstance: GooglePayUtils? = null

        val instance: GooglePayUtils
            get() {
                if (null == mInstance) {
                    synchronized(GooglePayUtils::class.java) {
                        if (null == mInstance) {
                            mInstance = GooglePayUtils()
                        }
                    }
                }
                return mInstance!!
            }
    }

    init {
        billingClient.startConnection(billingClientStateListener)
    }
    fun start(entity: OrderCreateEntity,context: Context,callBack: EmptySuccessCallBack) {
        this.context=context
        this.data=entity

        if (billingClient.connectionState == 0){
            startConnectionNumber=0
            billingClient.startConnection(billingClientStateListener)
        }
        this.callBack = callBack
        Log.e("~~~", "start: $mBillingResult")
        if(billingClient.isReady) {
            // The BillingClient is ready. You can query purchases here.
            getProductDetail(entity)
        }else{
            ToastUtil.toast("Something went wrong,Please try again later")
            mBillingResult?.let { handleBillingResult(300,it) }
        }

    }


    fun handleBillingResult(type:Int,billingResult: BillingResult){
        if (billingResult.responseCode==BillingClient.BillingResponseCode.SERVICE_DISCONNECTED){
            billingClient.startConnection(billingClientStateListener)
        }
        DotInit.listenet?.oldExecute(type,billingResult.toString())
    }

    /**
     * 获取商品详情
     */
    private fun getProductDetail(entity: OrderCreateEntity) {
        mEntity = entity
        val queryProductDetailsParams =
            QueryProductDetailsParams.newBuilder().setProductList(
                mutableListOf(
                    QueryProductDetailsParams.Product.newBuilder()
                        .setProductId(if (entity.data.purchaseType == 1) entity.data.productCode else entity.data.purchaseProductName)
                        .setProductType(if (entity.data.purchaseType == 1) BillingClient.ProductType.INAPP else BillingClient.ProductType.SUBS)
                        .build()
                )
            ).build()
        billingClient.queryProductDetailsAsync(queryProductDetailsParams) { billingResult,
                                                                            productDetailsList ->
            if (billingResult.responseCode!=BillingClient.BillingResponseCode.OK){
                handleBillingResult(312,billingResult)
            }else{
                bugProduct(productDetailsList, entity)
            }
        }
    }

    /**
     * 购买商品
     */
    private fun bugProduct(
        productDetailsList: List<ProductDetails>,
        entity: OrderCreateEntity
    ) {
        if (com.google.android.gms.common.util.CollectionUtils.isEmpty(productDetailsList)) {
            DotInit.listenet?.oldExecute(312,"Product Details List is empty")
        }
        // check billingResult
        // process returned productDetailsList
        if (!CollectionUtils.checkNullOrEmptyOrContainsNull(productDetailsList)) {
            val productDetailsParamsList: List<BillingFlowParams.ProductDetailsParams>
            //获取订阅信息
            if (productDetailsList[0].subscriptionOfferDetails != null) {
                var offerToken = ""
                for (i in 0 until (productDetailsList[0].subscriptionOfferDetails?.size
                    ?: 0)) {
                    if (productDetailsList[0].subscriptionOfferDetails!![i].basePlanId == entity.data.productCode) {
                        offerToken =
                            productDetailsList[0].subscriptionOfferDetails!![i].offerToken
                    }
                }
                productDetailsParamsList = listOf(
                    BillingFlowParams.ProductDetailsParams.newBuilder()
                        // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
                        .setProductDetails(productDetailsList[0])
                        // to get an offer token, call ProductDetails.subscriptionOfferDetails()
                        // for a list of offers that are available to the user
                        .setOfferToken(offerToken)
                        .build()
                )
            } else {
                //购买单个产品
                productDetailsParamsList = listOf(
                    BillingFlowParams.ProductDetailsParams.newBuilder()
                        .setProductDetails(productDetailsList[0])
                        .build()
                )
            }

            val billingFlowParams: BillingFlowParams =
                if (mEntity?.data?.latestPaidOrderPurchaseToken != null) {
                    BillingFlowParams.newBuilder()
                        .setProductDetailsParamsList(productDetailsParamsList)
                        .setSubscriptionUpdateParams(
                            BillingFlowParams.SubscriptionUpdateParams.newBuilder()
                                .setOldPurchaseToken(mEntity?.data?.latestPaidOrderPurchaseToken!!)
                                .setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_FULL_PRICE)
                                .build()
                        )
                        .build()
                } else {
                    BillingFlowParams.newBuilder()
                        .setProductDetailsParamsList(productDetailsParamsList)
                        .build()
                }
            val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
            if (billingResult.responseCode != BillingResponseCode.OK) {
                handleBillingResult(313,billingResult)
            }
        }
    }

    fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
        Log.e("~~~", "onPurchasesUpdated=====: $billingResult" )

        if (billingResult.responseCode == BillingClient.BillingResponseCode.OK && purchases != null) {
            Log.e("~~~", "onPurchasesUpdated: ${purchases.size}" )
            for(purchase in purchases){
                Log.e("~~~", "onPurchasesUpdated: ${purchase.purchaseState}  --- ${purchase}" )
                handlePurchase(purchase)
            }
        } else {
            if (billingResult.responseCode != BillingClient.BillingResponseCode.OK){
                handleBillingResult(315,billingResult)
            }
        }
    }

    var requestNum=0

    fun handlePurchase(purchase: Purchase) {
        if (mEntity?.data?.purchaseType == 1){
            val consumeParams = ConsumeParams.newBuilder()
                .setPurchaseToken(purchase.purchaseToken)
                .build()

            val listener = ConsumeResponseListener { billingResult, purchaseToken ->
                if (billingResult.responseCode == BillingResponseCode.OK) {
                    requestNum=0
                    storeToken(purchase)
                    SDEventManager.post(mEntity, EnumEventTag.PAY_RESULT.ordinal)
                }
            }
            billingClient.consumeAsync(consumeParams, listener)
        }else{
            if (purchase.purchaseState === PurchaseState.PURCHASED) {
                if (!purchase.isAcknowledged) {
                    val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
                        .setPurchaseToken(purchase.purchaseToken)
                        .build()
                    billingClient.acknowledgePurchase(acknowledgePurchaseParams) { billingResult ->
                        if (billingResult.responseCode == BillingResponseCode.OK) {
                            storeToken(purchase)
                        }
                    }
                }
            }
        }
    }




    private fun storeToken(purchase: Purchase) {
        OkHttpManager.instance.requestInterface(object : OkHttpFromBoy {
            override fun addBody(requestBody: OkHttpBodyEntity) {
                requestBody.setPost(API.user_order_token_url)
                requestBody.add("purchase", purchase.originalJson)
                requestBody.add("orderNoTmp", mEntity?.data!!.orderNo)
            }

        }, object : SDOkHttpResoutCallBack<OrderCreateEntity>(false) {
            override fun onSuccess(entity: OrderCreateEntity) {
                if (mEntity?.data?.purchaseType == 1) {
                    MemberBuySingleSuccessDialog(
                        SDActivityManager.instance.lastActivity,
                        mEntity?.data!!.productCategory,
                        mEntity?.data!!.benefitNum,
                        object : MemberBuySingleSuccessDialog.ChangeMembershipListener {
                            override fun onListener() {
                                callBack?.OnSuccessListener()
                            }
                        }).showPopupWindow()
                } else {
                    MemberBuySuccessPopup(
                        context!!,
                        object :
                            MemberBuySuccessPopup.ChangeMembershipListener {
                            override fun onListener() {
                                callBack?.OnSuccessListener()
                            }

                        }).showPopupWindow()
                }

            }

            override fun onFailure(code: Int, msg: String) {
                if (requestNum<3) {
                    storeToken(purchase)
                    requestNum++
                }
            }
        })
    }


}